﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Leffaetsin.Models;
using Leffaetsin.Services.Providers.IMDBProviders;

namespace Leffaetsin.Services.Providers.ShowProviders
{
    public static class ShowProvider
    {
        internal static FinnkinoProvider FinnkinoProvider { get { return new FinnkinoProvider(); } }
        internal static BioRexProvider BioRexProvider { get { return new BioRexProvider(); } }

        public static IEnumerable<string> GetAreas()
        {
            var areas = new List<string>();
            areas.AddRange(FinnkinoProvider.GetAreas().Select(e => e.Name));
            areas.AddRange(BioRexProvider.GetAreas().Select(e => e.Name));
            
            return areas.Distinct();
        }

        public static Movie GetMovie(string name, string areaName = "Pääkaupunkiseutu")
        {
            // TODO: known bug, groupataan originalanmen perusteella mutta haetaan title:n perusteella
            var keys = GetShows(areaName).Select(e => e.Key);
            // TODO: StripForApi():n kutsuminen purkkaa
            var shows = GetShows(areaName).Where(e => e.Key.StripForApi() == name.StripForApi()).SelectMany(e => e); // TODO: known bug, http://localhost:49553/Espoo/Helin%C3%A4-keiju%20ja%20siipien%20salaisuus%203D%20(puhumme%20suomea)
            if (!shows.Any())
                return new Movie();

            return GetMovieDto(areaName, shows.First(), shows);
        }

        public static IEnumerable<Movie> GetMovies(string areaName = "Pääkaupunkiseutu")
        {
            var movies = GetRawMovies(areaName).ToList();
            // use finnkino thumbnails, if possible
            foreach (var movie in movies.Where(m => m.IsBioRexMovie)) {
                var finnkinoMovie = movies.FirstOrDefault(m => m.OriginalTitle.StripForApi() == movie.OriginalTitle.StripForApi());
                if (finnkinoMovie != null) {
                    movie.ThumbNailUrl = finnkinoMovie.ThumbNailUrl;
                }
            }
            return movies;
        }

        private static IEnumerable<Movie> GetRawMovies(string areaName)
        {
            foreach (var shows in GetShows(areaName))
            {
                var currentMovie = shows.First();
                yield return GetMovieDto(areaName, currentMovie, shows);
            }
        }


        private static IEnumerable<IGrouping<string, GetMovieDto>> GetShows(string areaName)
        {
            var allMovies = new List<GetMovieDto>();
            allMovies.AddRange(FinnkinoProvider.GetShows(areaName));
            allMovies.AddRange(BioRexProvider.GetShows(areaName));

            // TODO: consider grouping by originaltitle.stripforapi??
            return allMovies.GroupBy(m => m.Title);
        }

        private static Movie GetMovieDto(string areaName, GetMovieDto currentMovie, IEnumerable<GetMovieDto> finnkinoMovies)
        {
            var showtimes = GetShowtimes(finnkinoMovies);

            var movie = new Movie()
            {
                AreaName = areaName,
                Title = currentMovie.Title,
                OriginalTitle = currentMovie.OriginalTitle,
                StrippedTitle = currentMovie.OriginalTitle.StripForApi(),
                ProductionYear = currentMovie.ProductionYear,
                FinnkinoLink = currentMovie.ShowURL,
                ThumbNailUrl = currentMovie.EventSmallImagePortrait,
                LargePicUrl = currentMovie.EventLargeImageLandscape,
                ShowTimes = showtimes.OrderBy(e => e),
                IsBioRexMovie = currentMovie is BiorexShow
            };
            return movie;
        }

        private static IEnumerable<string> GetShowtimes(IEnumerable<GetMovieDto> finnkinoMovies)
        {
            var groupedShowTimes = finnkinoMovies.GroupBy(m => m.TheatreRoom);
            var showtimes = new List<string>();
            foreach (var theatres in groupedShowTimes)
            {
                var shows = "";
                shows += (String.Format("{0} {1}: ", theatres.First().Theatre, theatres.First().TheatreRoom));
                shows += (String.Join(", ", theatres.Select(e => e.ShowTime.ToString("H:mm"))));
                showtimes.Add(shows);
            }
            return showtimes;
        }
    }
    static class Extensions
    {
        public static void AddRange<T>(this ICollection<T> collection, IEnumerable<T> list)
        {
            foreach (var item in list)
            {
                collection.Add(item);
            }
        }
    }

}